// 基础管理器类

import { RedisClient } from './RedisClient';
import { Logger } from '../types';
import { KeyGenerator } from '../utils/keyGenerator';
import { defaultLogger } from '../utils/logger';

export abstract class BaseManager {
  protected client: RedisClient;
  protected logger: Logger;
  protected keyGenerator: KeyGenerator;

  constructor(client: RedisClient, keyGenerator?: KeyGenerator) {
    this.client = client;
    const clientLogger = (client as any).logger;
    this.logger =
      clientLogger?.createChild?.(this.constructor.name) ??
      defaultLogger.createChild(this.constructor.name);
    this.keyGenerator = keyGenerator ?? new KeyGenerator();
  }

  /**
   * 执行Redis命令的包装方法
   */
  protected async execute<T = any>(command: string, ...args: any[]): Promise<T> {
    return this.client.execute<T>(command, ...args);
  }

  /**
   * 设置值的包装方法
   */
  protected async setValue(key: string, value: any, ttl?: number): Promise<void> {
    return this.client.set(key, value, ttl);
  }

  /**
   * 获取值的包装方法
   */
  protected async getValue<T = any>(key: string): Promise<T | null> {
    return this.client.get<T>(key);
  }

  /**
   * 删除键的包装方法
   */
  protected async deleteKeys(...keys: string[]): Promise<number> {
    return this.client.del(...keys);
  }

  /**
   * 检查键是否存在
   */
  protected async keyExists(...keys: string[]): Promise<number> {
    return this.client.exists(...keys);
  }

  /**
   * 设置过期时间
   */
  protected async setExpire(key: string, seconds: number): Promise<number> {
    return this.client.expire(key, seconds);
  }

  /**
   * 获取TTL
   */
  protected async getTtl(key: string): Promise<number> {
    return this.client.ttl(key);
  }

  /**
   * 获取匹配的键
   */
  protected async getKeys(pattern: string): Promise<string[]> {
    return this.client.keys(pattern);
  }

  /**
   * 创建管道
   */
  protected createPipeline(): any {
    return this.client.pipeline();
  }

  /**
   * 创建事务
   */
  protected createTransaction(): any {
    return this.client.multi();
  }

  /**
   * 生成键
   */
  protected generateKey(...parts: (string | number)[]): string {
    return this.keyGenerator.generate(...parts);
  }

  /**
   * 批量操作辅助方法
   */
  protected async batchExecute<T>(operations: Array<() => Promise<T>>): Promise<T[]> {
    const results: T[] = [];

    for (const operation of operations) {
      try {
        const result = await operation();
        results.push(result);
      } catch (error) {
        this.logger.error('Batch operation failed', { error });
        throw error;
      }
    }

    return results;
  }

  /**
   * 重试机制
   */
  protected async withRetry<T>(
    operation: () => Promise<T>,
    maxAttempts: number = 3,
    delay: number = 1000
  ): Promise<T> {
    let lastError: Error;

    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error as Error;

        if (attempt === maxAttempts) {
          break;
        }

        this.logger.warn(`Operation failed, retrying (${attempt}/${maxAttempts})`, {
          error: lastError.message,
          attempt,
        });

        await this.sleep(delay * attempt);
      }
    }

    throw lastError!;
  }

  /**
   * 睡眠辅助方法
   */
  protected sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 验证参数
   */
  protected validateRequired(params: Record<string, any>): void {
    for (const [key, value] of Object.entries(params)) {
      if (value === undefined || value === null || value === '') {
        throw new Error(`Required parameter '${key}' is missing or empty`);
      }
    }
  }

  /**
   * 验证数字参数
   */
  protected validateNumber(value: any, name: string, min?: number, max?: number): number {
    const num = Number(value);

    if (isNaN(num) || !isFinite(num)) {
      throw new Error(`Parameter '${name}' must be a valid number`);
    }

    if (min !== undefined && num < min) {
      throw new Error(`Parameter '${name}' must be >= ${min}`);
    }

    if (max !== undefined && num > max) {
      throw new Error(`Parameter '${name}' must be <= ${max}`);
    }

    return num;
  }

  /**
   * 验证字符串参数
   */
  protected validateString(
    value: any,
    name: string,
    minLength?: number,
    maxLength?: number
  ): string {
    if (typeof value !== 'string') {
      throw new Error(`Parameter '${name}' must be a string`);
    }

    if (minLength !== undefined && value.length < minLength) {
      throw new Error(`Parameter '${name}' must be at least ${minLength} characters long`);
    }

    if (maxLength !== undefined && value.length > maxLength) {
      throw new Error(`Parameter '${name}' must be at most ${maxLength} characters long`);
    }

    return value;
  }

  /**
   * 格式化错误信息
   */
  protected formatError(error: any, context?: string): Error {
    const message = context
      ? `${context}: ${error instanceof Error ? error.message : String(error)}`
      : error instanceof Error
        ? error.message
        : String(error);

    return new Error(message);
  }

  /**
   * 记录操作指标
   */
  protected logMetric(operation: string, duration: number, success: boolean, metadata?: any): void {
    this.logger.debug('Operation metric', {
      operation,
      duration,
      success,
      metadata,
    });
  }

  /**
   * 获取当前时间戳
   */
  protected now(): number {
    return Date.now();
  }

  /**
   * 获取当前日期
   */
  protected today(): Date {
    return new Date();
  }

  /**
   * 格式化日期为字符串
   */
  protected formatDate(
    date: Date,
    format: 'YYYY-MM-DD' | 'YYYY-MM' | 'YYYY' = 'YYYY-MM-DD'
  ): string {
    switch (format) {
      case 'YYYY':
        return date.getFullYear().toString();
      case 'YYYY-MM':
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
      case 'YYYY-MM-DD':
      default:
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }
  }
}
